# encoding=utf-8
import json
import os
import random
import time
import requests
from urllib.parse import urlparse

from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework import exceptions, status

# Create your views here.
from rest_framework.response import Response
from rest_framework.views import APIView

from configer import EMAIL_SERVE_HOST, EMAIL_SERVE_PASS
from configer import LOG
from middlewares.auth import login_and_auth_middleware, image_cache_middleware, CsrfExemptSessionAuthentication
from middlewares.auto_speed import speed_limit_middleware, log_middleware
from user_app import models
from user_app.serializers import UserSimpleSerializer, UserDetailSerializer, UserLoginSerializer
from utils.encode_decode import bw_encode
from utils.file_helper import upload_image_to_local
from utils.my_jwt import MiniJWT
from utils.regexp_rule import EMAIL


def welcome(request, template=None):
    """欢迎页面"""
    dic = {
        "/": "homePage.html",
        "personalPage.html": "personalPage.html",
        "editorBywang.html": "editorBywang.html",
        "editorByEditorMD.html": "editorByEditorMD.html",
        "editorBywangPatch.html": "editorBywangPatch.html",
        "editorByEditorMDPatch.html": "editorByEditorMDPatch.html",
        "sign-in.html": "sign-in.html",
        "sign-up.html": "sign-up.html",
        "showEditorBywang.html":  "showEditorBywang.html",
        "showEditorByEditorMD.html":  "showEditorByEditorMD.html",
        "adminArticleBywang.html": "adminArticleBywang.html",
        "adminArticleByEditorMD.html": "adminArticleByEditorMD.html",
        "userInstruction.html": "userInstruction.html",
        "adminArticle.html": "adminArticle.html"
    }
    pk = request.GET.get('p', "1")
    mode = request.GET.get('mode', "1")
    url = urlparse(request.get_full_path()).path
    if url.startswith('/page'):
        url = template
    return render(request, dic.get(url, 'homePage.html'), {"pk": json.dumps(pk)})


class UserView(APIView):
    """负责获取全部用户和注册"""

    @log_middleware
    @speed_limit_middleware
    @login_and_auth_middleware
    def get(self, request):
        """查看用户个人信息"""
        uid = request.META["mini_uid"]
        user = models.User.objects.get(pk=uid)
        bs = UserSimpleSerializer(user)
        return Response(bs.data)

    @log_middleware
    @speed_limit_middleware
    @image_cache_middleware
    def post(self, request):
        """注册接口"""
        bs = UserDetailSerializer(data=request.data)
        if bs.is_valid(raise_exception=True):
            cache = request.data.get("cache", "")
            email = bs.validated_data['email']
            if cache != self.get_cache(email):
                return Response({"message": "验证码错误", "code": 3001})
            self.remove_cache(email)
            bs.validated_data['password'] = bw_encode(str(bs.validated_data['password']))  # 修改密码
            bs.save()
            return Response({"message": "注册成功", "data": bs.data})
        else:
            return Response(bs.errors)

    @log_middleware
    @speed_limit_middleware
    @login_and_auth_middleware
    def put(self, request):
        """修改接口"""
        uid = request.META["mini_uid"]
        user = models.User.objects.get(pk=uid)
        info = request.data.get("info", "这个用户很懒 什么也没留下")
        user.info = info[:100]
        user.save()
        return Response({"message": "修改成功"})
        
    @log_middleware
    @speed_limit_middleware
    @login_and_auth_middleware
    def delete(self, request):
        """用户注销"""
        uid = request.META["mini_uid"]
        password = request.data.get("password", "")
        user = models.User.objects.get(pk=uid)
        if user.password == bw_encode(password):
            user.is_delete = 1
            user.save()
            return Response({"message": "注销成功"})
        return Response({"message": "密码错误", "code": 3001})

    def remove_cache(self, email):
        redis_conn = get_redis_connection('default')
        redis_conn.delete(email)

    def get_cache(self, email):
        """获取邮箱验证码"""
        redis_conn = get_redis_connection('default')
        data = redis_conn.get(email)
        return data.decode('utf-8') if data else "010101"


class CacheView(APIView):
    """提供注册、找回密码等需要验证邮箱的接口"""

    @log_middleware
    def post(self, request):
        email = request.data.get("email", "")
        # 正则验证
        if not EMAIL.search(email):
            return Response({"message": "请填入正确的邮箱", "code": 200})
        # redis验证
        if self.check_cache(email):
            return Response({"message": "5分钟内已发送 请勿频繁请求", "code": 200})
        # 发送邮件
        code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
        res = self.save_cache(email, code)
        if not res:
            return Response({"message": "发送失败", "code": 3001})
        # 返回结果
        return Response({"message": "发送成功", "code": 200})

    def check_cache(self, email):
        """检查是否5分钟内存在"""
        redis_conn = get_redis_connection('default')
        data = redis_conn.get(email)
        return True if data else False

    def save_cache(self, email, code):
        """存入redis"""
        retry_count = 3
        while retry_count:
            try:
                payload = {
                    "email": email,
                    "info": f'【黑白空间】本次验证码：{code} 【5分钟有效】',
                    "pass": EMAIL_SERVE_PASS
                }
                res = requests.post(f'http://{EMAIL_SERVE_HOST}/', data=payload)
            except:
                retry_count -= 1
                continue
            if res.status_code == 200:
                redis_conn = get_redis_connection('default')
                redis_conn.set(email, code, 5 * 60)
                return True
        return False


class UserAuthView(APIView):

    @log_middleware
    @speed_limit_middleware
    @login_and_auth_middleware
    def get(self, request):
        """权限验证接口"""
        uid = request.META.get("mini_uid")
        user = models.User.objects.get(pk=uid)
        return Response({"user": user.nick_name})


class AvatarView(APIView):

    @log_middleware
    @speed_limit_middleware
    def get(self, request):
        """查看所有用户接口"""
        ...
        return Response({"data": []})

    @log_middleware
    @speed_limit_middleware
    @login_and_auth_middleware
    def post(self, request):
        """修改头像"""
        image_file = request.FILES.get("file")
        if not image_file:
            return Response({"message": "上传图片为空", "code": 201})
        file_name, file_status, info = upload_image_to_local(image_file)
        if not file_status:
            return Response({"message": info, "code": status.HTTP_400_BAD_REQUEST})
        uid = request.META["mini_uid"]
        user = models.User.objects.get(pk=uid)
        user.avatar = f'/static/user_static/{file_name}'
        user.save()
        return Response({"message": info, "file_name": f'/static/user_static/{file_name}'})


class LoginView(APIView):
    """负责用户登录"""

    authentication_classes = (CsrfExemptSessionAuthentication,)

    @log_middleware
    @speed_limit_middleware
    @image_cache_middleware
    def post(self, request, *args, **kwargs):
        """登录接口"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]  #所以这里是真实的ip
        else:
            ip = request.META.get('REMOTE_ADDR')  #这里获得代理ip
        # LOG.info(f"登录ip：--> {str(ip)}")
        ua = request.META.get('HTTP_USER_AGENT', '')
        bs = UserLoginSerializer(data=request.data)
        if bs.is_valid(raise_exception=True):
            email = bs.validated_data['email']
            user = models.User.objects.filter(email=email, is_delete=0, is_valid=1).first()
            if not user:
                raise exceptions.ValidationError(f'用户状态异常', 3001)
            if user.password != bw_encode(str(bs.validated_data['password'])):
                raise exceptions.ValidationError(f'此密码不匹配', 3002)
            user.last_login_time = time.time()
            user.save()
            jwt = MiniJWT()
            jwt_code = jwt.build(user.id, user.level, ip, ua)
            results = Response({"data": bs.data, "token": "test", "avatar": user.avatar, "nick_name": user.nick_name, "message": "登录成功"})
            results.set_cookie('jwtToken', jwt_code, expires=3600)
            # LOG.info(f"用户登录访问ip：--> {str(ip)}  {ua}  {jwt_code}")
            return results
        else:
            raise exceptions.ValidationError(bs.errors)


class PingView(APIView):
    """负责维持登录"""

    @log_middleware
    @login_and_auth_middleware
    def get(self, request):
        """GET接口"""
        ...
        return Response({"data": []})